package com.soxing.braindata.service.manager;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.soxing.braindata.dao.domain.request.ResearchSearchRequest;
import com.soxing.braindata.dao.domain.request.SearchRequest;
import com.soxing.braindata.dao.domain.vo.TinyResearch;
import com.soxing.braindata.dao.entity.*;
import com.soxing.braindata.dao.service.*;
import com.soxing.braindata.domain.enumeration.ComplianceRateEnum;
import com.soxing.braindata.domain.enumeration.QualityRateEnum;
import com.soxing.braindata.domain.enumeration.SexRateEnum;
import com.soxing.braindata.domain.response.RStat;
import com.soxing.braindata.domain.response.ResearchStat;
import com.soxing.braindata.domain.response.SStat;
import com.soxing.braindata.domain.stat.CollectEntity;
import com.soxing.braindata.domain.stat.FinishEntity;
import com.soxing.braindata.domain.stat.QAEntity;
import com.soxing.braindata.domain.stat.YearEntity;
import com.soxing.braindata.domain.vo.ResearchVo;
import com.soxing.common.utils.response.MyPage;
import com.soxing.common.utils.response.WebResponse;
import com.soxing.common.utils.util.ObjectMapper;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author :durango
 * @date :2022/6/11 15:03
 * @description 设备管理服务实现
 */
@Service
public class ResearchManagerImpl extends AbstractManager<Research> implements IResearchManager {

    @Resource
    private IResearchService researchService;
    @Resource
    private IResearchExtService researchExtService;
    @Resource
    private ISiteManager siteManager;
    @Resource
    private IStatItemResultService statItemResultService;

    @Resource
    private IUserInfoExtService userInfoExtService;

    @Resource
    private IRoleService roleService;

    @Resource
    private ISiteService siteService;

    @Override
    public IService<Research> getService() {
        return researchService;
    }

    @Override
    public LambdaQueryWrapper<Research> wrapSearchRequest(SearchRequest request) {
        ResearchSearchRequest searchRequest = (ResearchSearchRequest) request;
        if (request == null) {
            searchRequest = new ResearchSearchRequest();
        }
        Research obj = ObjectMapper.map(searchRequest, Research.class);
        LambdaQueryWrapper<Research> queryWrapper = new LambdaQueryWrapper<>(obj);
        if (StringUtils.isNotBlank(searchRequest.getResearchName())) {
            obj.setResearchName(null);
            queryWrapper.like(Research::getResearchName, searchRequest.getResearchName());
        }
        return queryWrapper;
    }

    @Override
    public WebResponse<MyPage<TinyResearch>> search(ResearchSearchRequest request) {
        Integer pageNum = request.getPageNum();
        Integer pageSize = request.getPageSize();
        if (pageNum == null || pageNum <= 0) {
            pageNum = 1;
        }
        if (pageSize == null || pageSize <= 0) {
            pageSize = 10;
        }
        Page<TinyResearch> page = new Page<>(pageNum, pageSize);
        IPage<TinyResearch> res = researchService.selectMyPage(page, request);
        if (res == null || CollectionUtils.isEmpty(res.getRecords())) {
            return WebResponse.success(new MyPage<>(1, 0, 0, new ArrayList<>()));
        }
        return WebResponse.success(new MyPage<>(pageNum, res.getPages(), res.getTotal(), res.getRecords()));
    }

    @Override
    public WebResponse<ResearchVo> getVoById(Integer id) {
        Research research = researchService.getById(id);
        Site site = siteManager.getSiteBysitePkId(research.getSitePkId());
        ResearchVo researchVo = ResearchVo.builder().research(research).site(site).build();
        return WebResponse.success(researchVo);
    }

    @Override
    public WebResponse<Research> getBysubjectPkId(String subjectPkId) {
        if (subjectPkId == null) {
            return null;
        }
        List<Research> researchList = researchService.list(new LambdaQueryWrapper<Research>().eq(Research::getSubjectPkId, subjectPkId));
        if (CollectionUtils.isEmpty(researchList)) {
            return null;
        }
        return WebResponse.success(researchList.get(0));
    }

    @Override
    public WebResponse<MyPage<Research>> getByResearchByUser(String userNum,int pageSize,int pageNum) {

        UserInfoExt userInfoExt = userInfoExtService.getOne(new LambdaQueryWrapper<UserInfoExt>().eq(UserInfoExt::getUserNum,userNum));
        Page<Research> result = null;
        Page<Research> page = new Page<>(pageNum, pageSize);
        if(userInfoExt.getUserType()==0)
        {

            result = researchService.page(page);
        }
        else
        {

            List<Role> roleList = roleService.list(new LambdaQueryWrapper<Role>().eq(Role::getUserPkId,userNum));
            Set<String> roleSubjectPkId = roleList.stream().map(
                    Role::getSubjectPkId
            ).collect(Collectors.toSet());


            result = researchService.page(page,new LambdaQueryWrapper<Research>().in(Research::getSubjectPkId,roleSubjectPkId));
        }


        if (result == null || CollectionUtils.isEmpty(result.getRecords())) {
            return WebResponse.success(new MyPage<>(1, 0, 0, new ArrayList<>()));
        }
        return WebResponse.success(new MyPage<>(pageNum, result.getPages(), result.getTotal(), result.getRecords()));

    }

    /**
     * 获取统计项
     *
     * @param
     * @return
     */
//    private ResearchStat getResearchStat(String subjectPkId) {
//
//        ResearchStat researchStat = new ResearchStat();
//        return researchStat;
//    }

    // 首页的监控
    public WebResponse<RStat> getResearchStatByUser(String userNum)
    {

        UserInfoExt userInfoExt = userInfoExtService.getOne(new LambdaQueryWrapper<UserInfoExt>().eq(UserInfoExt::getUserNum,userNum));
        List<ResearchExt> researchExtList = null;
        RStat sstat = new RStat();
        Set<String> roleSubjectPkIdSet = null;
        if(userInfoExt.getUserType()==0)//如果是系统管理员的话,返回所有的课题
        {
            researchExtList = researchExtService.list();
            if(researchExtList.size()>0){
                roleSubjectPkIdSet = researchExtList.stream().map(ResearchExt::getSubjectPkId).collect(Collectors.toSet());
                //目前research_pk_id的叫法有点乱,以后规整一下
            }
        }
        else
        {

            List<Role> roleList = roleService.list(new LambdaQueryWrapper<Role>().eq(Role::getUserPkId,userNum));

            roleSubjectPkIdSet = roleList.stream().map(
                    Role::getSubjectPkId
            ).collect(Collectors.toSet());

            researchExtList = researchExtService.list(new LambdaQueryWrapper<ResearchExt>().in(ResearchExt::getSubjectPkId,roleSubjectPkIdSet));
        }


        int[] researchcount = new int[3];//总数 进行中 终止
        researchExtList.forEach(
                //这个数据库的信息表示为 1 进行中 2 终止。
                item->{
                    researchcount[0]++;
                    if(item.getState()==0 || item.getState()==1)
                    {
                        researchcount[1]++;
                    }
                    else
                    {
                        researchcount[2]++;
                    }
                }
        );
        for(int i=0;i<researchcount.length;i++)
        {
            sstat.getResearchNumber().add(researchcount[i]);
        }


        List<StatItemResult> statItemList = statItemResultService.list(new LambdaQueryWrapper<StatItemResult>().in(StatItemResult::getSubjectPkId,roleSubjectPkIdSet));
        statItemList.forEach(
                item->{
                    if(item.getItemCode().equals(SexRateEnum.WOMAN.getKey()))
                    {
                        if(sstat.getSexRate().containsKey(SexRateEnum.WOMAN.getName()))
                        {
                            long num = sstat.getSexRate().get(SexRateEnum.WOMAN.getName())+item.getStatResult().longValue();
                            sstat.getSexRate().put(SexRateEnum.WOMAN.getName(),num);
                        }
                        else{
                            sstat.getSexRate().put(SexRateEnum.WOMAN.getName(),item.getStatResult().longValue());
                        }
                    }
                    else if(item.getItemCode().equals(SexRateEnum.MAN.getKey()))
                    {
                        if(sstat.getSexRate().containsKey(SexRateEnum.MAN.getName()))
                        {
                            long num = sstat.getSexRate().get(SexRateEnum.MAN.getName())+item.getStatResult().longValue();
                            sstat.getSexRate().put(SexRateEnum.MAN.getName(),num);
                        }
                        else{
                            sstat.getSexRate().put(SexRateEnum.MAN.getName(),item.getStatResult().longValue());
                        }
                    }


                    else if(item.getItemCode().equals(QualityRateEnum.HIGH.getKey()))
                    {
                        if(sstat.getQualityRate().containsKey(QualityRateEnum.HIGH.getName()))
                        {
                            long num = sstat.getQualityRate().get(QualityRateEnum.HIGH.getName())+item.getStatResult().longValue();
                            sstat.getQualityRate().put(QualityRateEnum.HIGH.getName(),num);
                        }
                        else{
                            sstat.getQualityRate().put(QualityRateEnum.HIGH.getName(),item.getStatResult().longValue());
                        }

                    }
                    else if(item.getItemCode().equals(QualityRateEnum.MIDDLE.getKey()))
                    {
                        if(sstat.getQualityRate().containsKey(QualityRateEnum.MIDDLE.getName()))
                        {
                            long num = sstat.getQualityRate().get(QualityRateEnum.MIDDLE.getName())+item.getStatResult().longValue();
                            sstat.getQualityRate().put(QualityRateEnum.MIDDLE.getName(),num);
                        }
                        else{
                            sstat.getQualityRate().put(QualityRateEnum.MIDDLE.getName(),item.getStatResult().longValue());
                        }

                    }
                    else if(item.getItemCode().equals(QualityRateEnum.LOW.getKey()))
                    {
                        if(sstat.getQualityRate().containsKey(QualityRateEnum.LOW.getName()))
                        {
                            long num = sstat.getQualityRate().get(QualityRateEnum.LOW.getName())+item.getStatResult().longValue();
                            sstat.getQualityRate().put(QualityRateEnum.LOW.getName(),num);
                        }
                        else{
                            sstat.getQualityRate().put(QualityRateEnum.LOW.getName(),item.getStatResult().longValue());
                        }

                    }


                    else if(item.getItemCode().equals(ComplianceRateEnum.HIGH.getKey()))
                    {
                        if(sstat.getComplianceRate().containsKey(ComplianceRateEnum.HIGH.getName()))
                        {
                            long num = sstat.getComplianceRate().get(ComplianceRateEnum.HIGH.getName())+item.getStatResult().longValue();
                            sstat.getComplianceRate().put(ComplianceRateEnum.HIGH.getName(),num);
                        }
                        else{
                            sstat.getComplianceRate().put(ComplianceRateEnum.HIGH.getName(),item.getStatResult().longValue());
                        }
                    }
                    else if(item.getItemCode().equals(ComplianceRateEnum.MIDDLE.getKey()))
                    {
                        if(sstat.getComplianceRate().containsKey(ComplianceRateEnum.MIDDLE.getName()))
                        {
                            long num = sstat.getComplianceRate().get(ComplianceRateEnum.MIDDLE.getName())+item.getStatResult().longValue();
                            sstat.getComplianceRate().put(ComplianceRateEnum.MIDDLE.getName(),num);
                        }
                        else{
                            sstat.getComplianceRate().put(ComplianceRateEnum.MIDDLE.getName(),item.getStatResult().longValue());
                        }
                    }
                    else if(item.getItemCode().equals(ComplianceRateEnum.LOW.getKey()))
                    {
                        if(sstat.getComplianceRate().containsKey(ComplianceRateEnum.LOW.getName()))
                        {
                            long num = sstat.getComplianceRate().get(ComplianceRateEnum.LOW.getName())+item.getStatResult().longValue();
                            sstat.getComplianceRate().put(ComplianceRateEnum.LOW.getName(),num);
                        }
                        else{
                            sstat.getComplianceRate().put(ComplianceRateEnum.LOW.getName(),item.getStatResult().longValue());
                        }
                    }

                    else if(item.getItemCode().equals(CollectEntity.key))
                    {
                        HashMap<String,Object> map =
                                JSONObject.parseObject(item.getStatJson(), HashMap.class);
//                      在后端进行日期排序 在前端调用echart 日期框架即可
                        Map<String,Object> treestat = new TreeMap<>(new Comparator<Object>() {

                            @SneakyThrows
                            @Override
                            public int compare(Object o1, Object o2) {
                                if(o1 instanceof String && o2 instanceof String) {
                                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                                    Date sd1=df.parse((String) o1);
                                    Date sd2=df.parse((String) o2);
                                    return sd1.compareTo(sd2);
                                }
                                return 0;
                            }

                        });
                        treestat.putAll(map);
                        //List<Site> siteList = siteService.list(new LambdaQueryWrapper<Site>().in(Site::getSitePkId,item.getSitePkId()));
                        Site site = siteService.getOne(new LambdaQueryWrapper<Site>().eq(Site::getSitePkId,item.getSitePkId()));
                        Map<String,Map<String,Object>> collectionBar = sstat.getCollectionBar();
                        if(site!=null)
                        {
                            if(collectionBar.containsKey(site.getSiteName()))
                            {
                                Map<String,Object> map2 = collectionBar.get(site.getSiteName());
                                mapPutAll(treestat,map2);
                                sstat.getCollectionBar().put(site.getSiteName(),treestat);
                            }
                            else
                            {
                                sstat.getCollectionBar().put(site.getSiteName(),treestat);
                            }

                        }

                    }
                    else if(item.getItemCode().equals(FinishEntity.key))
                    {
                        HashMap<String,Object> map =
                                JSONObject.parseObject(item.getStatJson(), HashMap.class);

                        Research research = researchService.getOne(new LambdaQueryWrapper<Research>().eq(Research::getSubjectPkId,item.getSubjectPkId()));
                        Map<String,Map<String,Object>> finishBar = sstat.getFinishBar();
                        if(research!=null)
                        {
                            if(finishBar.containsKey(research.getResearchName()))
                            {
                                Map<String,Object> map2 = finishBar.get(research.getResearchName());
                                mapPutAll(map,map2);
                                finishBar.put(research.getResearchName(),map);
                            }
                            else
                            {
                                finishBar.put(research.getResearchName(),map);
                            }

                        }

                        //sstat.setFinishBar(map);

                    }
                    else if(item.getItemCode().equals(QAEntity.key))
                    {
                        HashMap<String,Object> map =
                                JSONObject.parseObject(item.getStatJson(), HashMap.class);
                        Map<String,Object> QABar = sstat.getQABar();
                        map.forEach((k,v)->{
                            if(QABar.containsKey(k))
                            {
                                int num = (int) QABar.get(k) + (int) v;
                                QABar.put(k,num);

                            }
                            else{
                                QABar.put(k,v);
                            }

                        });
                    }
                    else if(item.getItemCode().equals(YearEntity.key))
                    {
                        HashMap<String,Object> map =
                                JSONObject.parseObject(item.getStatJson(), HashMap.class);
                        // sstat.setYearBar(map);


                        Map<String,Object> yearBar = sstat.getYearBar();
                        map.forEach((k,v)->{
                            if(yearBar.containsKey(k))
                            {
                                int num = (int) yearBar.get(k) + (int) v;
                                yearBar.put(k,num);
                            }
                            else
                            {
                                yearBar.put(k,v);
                            }

                        });

                    }





                }
        );
        return WebResponse.success(sstat);


    }


    //总平台管理员和队列管理员需要对某一队列进行监控
    @Override
    public WebResponse<RStat> getResearchStat(String subjectPkId)
    {
        RStat sstat = new RStat();
//        List<StatItemResult> man = statItemResultService.list(new LambdaQueryWrapper<StatItemResult>().in(StatItemResult::getSitePkId,sitePkId).in(StatItemResult::getItemCode, SexRateEnum.MAN.getKey()));
//        statItemResultService.list(new LambdaQueryWrapper<StatItemResult>().in(StatItemResult::getSitePkId,sitePkId).in(StatItemResult::getItemCode, SexRateEnum.WOMAN.getKey()));
        List<StatItemResult> statItemList = statItemResultService.list(new LambdaQueryWrapper<StatItemResult>().in(StatItemResult::getSubjectPkId,subjectPkId));
        statItemList.forEach(
                item->{
                    if(item.getItemCode().equals(SexRateEnum.WOMAN.getKey()))
                    {
                        if(sstat.getSexRate().containsKey(SexRateEnum.WOMAN.getName()))
                        {
                            long num = sstat.getSexRate().get(SexRateEnum.WOMAN.getName())+item.getStatResult().longValue();
                            sstat.getSexRate().put(SexRateEnum.WOMAN.getName(),num);
                        }
                        else{
                            sstat.getSexRate().put(SexRateEnum.WOMAN.getName(),item.getStatResult().longValue());
                        }
                    }
                    else if(item.getItemCode().equals(SexRateEnum.MAN.getKey()))
                    {
                        if(sstat.getSexRate().containsKey(SexRateEnum.MAN.getName()))
                        {
                            long num = sstat.getSexRate().get(SexRateEnum.MAN.getName())+item.getStatResult().longValue();
                            sstat.getSexRate().put(SexRateEnum.MAN.getName(),num);
                        }
                        else{
                            sstat.getSexRate().put(SexRateEnum.MAN.getName(),item.getStatResult().longValue());
                        }
                    }


                    else if(item.getItemCode().equals(QualityRateEnum.HIGH.getKey()))
                    {
                        if(sstat.getQualityRate().containsKey(QualityRateEnum.HIGH.getName()))
                        {
                            long num = sstat.getQualityRate().get(QualityRateEnum.HIGH.getName())+item.getStatResult().longValue();
                            sstat.getQualityRate().put(QualityRateEnum.HIGH.getName(),num);
                        }
                        else{
                            sstat.getQualityRate().put(QualityRateEnum.HIGH.getName(),item.getStatResult().longValue());
                        }

                    }
                    else if(item.getItemCode().equals(QualityRateEnum.MIDDLE.getKey()))
                    {
                        if(sstat.getQualityRate().containsKey(QualityRateEnum.MIDDLE.getName()))
                        {
                            long num = sstat.getQualityRate().get(QualityRateEnum.MIDDLE.getName())+item.getStatResult().longValue();
                            sstat.getQualityRate().put(QualityRateEnum.MIDDLE.getName(),num);
                        }
                        else{
                            sstat.getQualityRate().put(QualityRateEnum.MIDDLE.getName(),item.getStatResult().longValue());
                        }

                    }
                    else if(item.getItemCode().equals(QualityRateEnum.LOW.getKey()))
                    {
                        if(sstat.getQualityRate().containsKey(QualityRateEnum.LOW.getName()))
                        {
                            long num = sstat.getQualityRate().get(QualityRateEnum.LOW.getName())+item.getStatResult().longValue();
                            sstat.getQualityRate().put(QualityRateEnum.LOW.getName(),num);
                        }
                        else{
                            sstat.getQualityRate().put(QualityRateEnum.LOW.getName(),item.getStatResult().longValue());
                        }

                    }


                    else if(item.getItemCode().equals(ComplianceRateEnum.HIGH.getKey()))
                    {
                        if(sstat.getComplianceRate().containsKey(ComplianceRateEnum.HIGH.getName()))
                        {
                            long num = sstat.getComplianceRate().get(ComplianceRateEnum.HIGH.getName())+item.getStatResult().longValue();
                            sstat.getComplianceRate().put(ComplianceRateEnum.HIGH.getName(),num);
                        }
                        else{
                            sstat.getComplianceRate().put(ComplianceRateEnum.HIGH.getName(),item.getStatResult().longValue());
                        }
                    }
                    else if(item.getItemCode().equals(ComplianceRateEnum.MIDDLE.getKey()))
                    {
                        if(sstat.getComplianceRate().containsKey(ComplianceRateEnum.MIDDLE.getName()))
                        {
                            long num = sstat.getComplianceRate().get(ComplianceRateEnum.MIDDLE.getName())+item.getStatResult().longValue();
                            sstat.getComplianceRate().put(ComplianceRateEnum.MIDDLE.getName(),num);
                        }
                        else{
                            sstat.getComplianceRate().put(ComplianceRateEnum.MIDDLE.getName(),item.getStatResult().longValue());
                        }
                    }
                    else if(item.getItemCode().equals(ComplianceRateEnum.LOW.getKey()))
                    {
                        if(sstat.getComplianceRate().containsKey(ComplianceRateEnum.LOW.getName()))
                        {
                            long num = sstat.getComplianceRate().get(ComplianceRateEnum.LOW.getName())+item.getStatResult().longValue();
                            sstat.getComplianceRate().put(ComplianceRateEnum.LOW.getName(),num);
                        }
                        else{
                            sstat.getComplianceRate().put(ComplianceRateEnum.LOW.getName(),item.getStatResult().longValue());
                        }
                    }

                    else if(item.getItemCode().equals(CollectEntity.key))
                    {

                        HashMap<String,Object> map =
                                JSONObject.parseObject(item.getStatJson(), HashMap.class);

                        Map<String,Object> treestat = new TreeMap<>(new Comparator<Object>() {

                            @SneakyThrows
                            @Override
                            public int compare(Object o1, Object o2) {
                                if(o1 instanceof String && o2 instanceof String) {
                                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                                    Date sd1=df.parse((String) o1);
                                    Date sd2=df.parse((String) o2);
                                    return sd1.compareTo(sd2);
                                }
                                return 0;
                            }

                        });
                        treestat.putAll(map);

                        List<Site> siteList = siteService.list(new LambdaQueryWrapper<Site>().in(Site::getSitePkId,item.getSitePkId()));
                        if(!siteList.isEmpty())
                            sstat.getCollectionBar().put(siteList.get(0).getSiteName(),treestat);
                    }
                    else if(item.getItemCode().equals(QAEntity.key))
                    {
                        HashMap<String,Object> map =
                                JSONObject.parseObject(item.getStatJson(), HashMap.class);
                        Map<String,Object> QABar = sstat.getQABar();
                        map.forEach((k,v)->{
                            if(QABar.containsKey(k))
                            {
                                int num = (int) QABar.get(k) + (int) v;
                                QABar.put(k,num);

                            }
                            else{
                                QABar.put(k,v);
                            }

                        });
                    }
                    else if(item.getItemCode().equals(YearEntity.key))
                    {
                        HashMap<String,Object> map =
                                JSONObject.parseObject(item.getStatJson(), HashMap.class);
                        // sstat.setYearBar(map);


                        Map<String,Object> yearBar = sstat.getYearBar();
                        map.forEach((k,v)->{
                            if(yearBar.containsKey(k))
                            {
                                int num = (int) yearBar.get(k) + (int) v;
                                yearBar.put(k,num);
                            }
                            else
                            {
                                yearBar.put(k,v);
                            }

                        });

                    }





                }
        );
        return WebResponse.success(sstat);


    }


    public void mapPutAll(Map<String,Object> map1,Map<String,Object> map2)
    {



        map2.forEach((k,v)->
        {
            if(map1.containsKey(k))
            {
                if(v instanceof Integer&&map1.get(k) instanceof Integer)
                map1.put(k,(int)map2.get(k)+(int)v);
            }
            else{
                map1.put(k,v);
            }
        });

    }







}

